package com.durian.base.net.request;

import androidx.lifecycle.Lifecycle;

import com.durian.base.net.DownloadTaskManager;
import com.durian.base.net.HttpConfig;
import com.durian.base.net.HttpResponse;
import com.durian.base.net.IHttpTask;
import com.durian.base.net.Utils;
import com.durian.base.net.cache.IHttpCacheManager;
import com.durian.base.net.cache.NoneHttpCacheManager;
import com.durian.base.net.listener.OnDownloadListener;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 说明：OkDownload
 * <p/>
 * 作者：fanly
 * <p/>
 * 类型：Class
 * <p/>
 * 时间：2019/2/18 17:18
 * <p/>
 * 版本：version 1.0
 */
public class OkDownload extends AbstractHttpTask {

    protected File          mFile;
    protected OnDownloadListener mOnDownloadListener;
    protected Call          mCall;
    protected long          timeOut = HttpConfig.Constant.TIME_OUT;
    private static OkHttpClient downloadClient = null;

    protected OkDownload(String url,File file) {
        super(null, url);
        this.mFile = file;
    }

    public synchronized static void initOkHttpClient(OkHttpClient client){
        downloadClient = client;
    }

    public synchronized static void initOkHttpClient(){
        if (downloadClient == null){
            downloadClient = new OkHttpClient();
        }
    }

    public static OkDownload create(String url,File file) {
        return new OkDownload(url, file);
    }

    public OkDownload setOnDownloadListener(OnDownloadListener listener) {
        mOnDownloadListener = listener;
        return this;
    }

    protected HttpResponse doInBackground() {
        Request.Builder builder = createRequestBuilder();
        if (builder != null) {
            Request request = builder.build();
            try {
                if (timeOut == HttpConfig.Constant.TIME_OUT) {
                    mCall = downloadClient.newCall(request);
                } else {
                    mCall = downloadClient.newBuilder().readTimeout(timeOut, TimeUnit.SECONDS).writeTimeout(timeOut, TimeUnit.SECONDS).connectTimeout(timeOut, TimeUnit.SECONDS).build().newCall(request);
                }
                HttpResponse httpResponse = HttpResponse.download(mCall.execute());
                if (httpResponse.isSuccess()){
                    String filePath = saveFile(httpResponse.getResponse());
                    if (filePath != null && mFile != null && mFile.exists()){
                        return httpResponse;
                    }else {
                        return HttpResponse.unkown(new RuntimeException("download error!"));
                    }
                }else {
                    return httpResponse;
                }
            } catch (Exception e) {
                Utils.eLog(e);
                if (e instanceof SocketTimeoutException || (e != null && e instanceof InterruptedException && (e.getMessage() != null && "timeout".equals(e.getMessage().toLowerCase())))) {
                    return HttpResponse.timeOut(e);
                } else {
                    return HttpResponse.unkown(e);
                }
            }
        } else {
            return super.doInBackground();
        }
    }

    public Request.Builder createRequestBuilder() {
        return new Request.Builder()
                .url(getUrl())
                .tag(getUrl());
    }

    @Override
    public IHttpTask start() {
        initOkHttpClient();
        if (mFile != null){
            DownloadTaskManager.get().addTask(this);
        }
        return this;
    }

    @Override
    public void onStartTask() {
        if (mOnDownloadListener != null){
            mOnDownloadListener.onStart();
        }
    }

    @Override
    public void onSuccessTask(HttpResponse response) {
        if (mOnDownloadListener != null){
            mOnDownloadListener.onSuccess(response,mFile);
        }
    }

    @Override
    public void onErrorTask(int errorCode, Exception e) {
        if (mOnDownloadListener != null){
            mOnDownloadListener.onError(errorCode,e.getMessage());
        }
    }

    private void progressTask(long current, final long total){
        if (mOnDownloadListener != null){
            final float percent = (total == 0 ? 0 : current * 100.0f / total);
            if (mLifeCycle != null) {
                if (mLifeCycle.getCurrentState() == Lifecycle.State.RESUMED) {
                    final long c = current;
                    DownloadTaskManager.get().getHandler().post(new Runnable() {
                        @Override
                        public void run() {
                            onProgressTask(c,total,percent);
                        }
                    });
                }
            } else {
                final long c = current;
                DownloadTaskManager.get().getHandler().post(new Runnable() {
                    @Override
                    public void run() {
                        onProgressTask(c,total,percent);
                    }
                });
            }

        }
    }

    protected void onProgressTask(long current,long total,float percent){
        if (mOnDownloadListener != null){
            mOnDownloadListener.onProgress(current,total,percent);
        }
    }

    protected String saveFile(Response response){
        String filePath = null;
        InputStream is = null;
        int len;
        long current = 0;
        byte[] buf = new byte[1024*2];
        FileOutputStream fos = null;
        try {
            is = response.body().byteStream();
            long total = response.body().contentLength();
            Utils.mkdirs(mFile.getParentFile());
            Utils.delete(mFile);

            fos = new FileOutputStream(mFile);
            while ((len = is.read(buf)) != -1){
                current += len;
                fos.write(buf,0,len);
                progressTask(current,total);
            }
            fos.flush();
            filePath = mFile.getAbsolutePath();
            progressTask(current,total);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            Utils.closeIO(is, fos);
            return filePath;
        }
    }

    @Override
    protected void doCancelTask() {
        super.doCancelTask();
        if (mCall != null && !mCall.isCanceled()) {
            try {
                mCall.cancel();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (mOnDownloadListener != null){
            mOnDownloadListener.onCancel();
        }
    }

    @Override
    public IHttpCacheManager getHttpCacheManager() {
        return NoneHttpCacheManager.create();
    }

    @Override
    public String getCacheKey() {
        return null;
    }

    @Override
    public String getCacheUrl() {
        return null;
    }
}
